extends CharacterBody2D

enum STATES {
	None,
	Idle,
	Run,
	Attack,
	Attack2,
	Attack3,
	Jump
}

@export var actor_data : ActorData
@export var can_combo : bool = false
@onready var anim_player : AnimationPlayer = $AnimationPlayer
@onready var model: Sprite2D = $Model
@onready var states: States = $States
@onready var attack_timer: Timer = $AttackTimer

#client
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var current_state : STATES
var last_state : STATES
var st : Dictionary = {}
var is_attacking : bool
var state_anim : Dictionary = {
	STATES.Idle : "idle",
	STATES.Run : "run",
	STATES.Attack : "attack",
	STATES.Attack2 : "attack2",
	STATES.Jump : "Hero/jump"
}
var combo_link : Dictionary = {
	2 : 3
}

func _enter_tree() -> void:
	set_multiplayer_authority(name.to_int())

func _ready() -> void:
	if not is_multiplayer_authority() : return
	var camera = Camera2D.new()
	camera.zoom *= 2.5
	camera.offset.y = -50.0
	camera.position_smoothing_enabled = true
	add_child(camera)
	_init_anim()
	anim_player.animation_finished.connect(_on_animation_finished_event)

func _init_anim() -> void :	
	st[STATES.Idle] = states.idle_state.new(self)
	st[STATES.Run] = states.run_state.new(self)
	st[STATES.Attack] = states.attack_state.new(self)
	st[STATES.Attack2] = states.attack_state.new(self)
	st[STATES.Attack3] = states.attack_state.new(self)
	st[STATES.Jump] = states.jump_state.new(self)
	_transition_state(STATES.Idle)

func _process(delta: float) -> void:
	if not is_multiplayer_authority() : return	
	var cs = st.get(current_state)
	if cs : cs._on_process(delta)

func _physics_process(delta: float) -> void:
	if not is_multiplayer_authority() : return
	
	var cs = st.get(current_state)
	if cs : cs._on_physics_process(delta)
	
	if is_attacking :#正在攻击
		velocity = Vector2.ZERO
	else :
		var right = Input.get_axis("ui_left","ui_right")
		velocity.x = right * actor_data.speed
		if not is_on_floor() :
			velocity.y += gravity * delta
			_transition_state(STATES.Jump)
		elif Input.is_action_just_pressed("jump") and is_on_floor():
			velocity.y = -actor_data.jump_speed
		elif is_same(velocity.x,0.0) and is_on_floor() :
			_transition_state(STATES.Idle)
		else :
			_transition_state(STATES.Run)
		if not is_same(right,0.0) :
			model.flip_h = right < 0
		
	move_and_slide()

func _transition_state(state : STATES) -> void :
	var ls = st.get(current_state)
	if ls : ls._on_exit()
	
	last_state = current_state
	current_state = state
	
	var cs = st.get(state)
	if cs : cs._on_enter(state)

@rpc("authority", "call_local", "unreliable", 0)
func _play_anim(state_name : STATES) -> void :
	var anim = state_anim.get(state_name)
	anim_player.play(anim)

func _on_animation_finished_event(anim_name: StringName) :
	var cs = st.get(current_state)
	if cs : cs._on_anim_finished(anim_name)

#authority：仅由主控端（如服务器）调用。
#any_peer：允许任何对等端调用。
#call_local：调用时在本地也执行。
#reliable/unreliable：设置数据传输的可靠性。
#@rpc("authority", "call_local", "reliable", 0)
func _attack() -> void :
	if is_attacking :
		if can_combo : 
			var combo = combo_link.get(current_state)
			if not combo : 
				return
			await anim_player.animation_finished
			_transition_state(combo)
		return
	if not attack_timer.is_stopped() : return
	print(name,"攻击")
	attack_timer.start(actor_data.attack_cd_time)
	_transition_state(STATES.Attack)
